home *** CD-ROM | disk | FTP | other *** search
/ Graphics Plus / Graphics Plus.iso / msdos / compresn / hv11 / src / viewer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-07  |  50.0 KB  |  1,805 lines

  1. /*  CONDITIONAL COMPILATION FLAGS  */
  2. #define BRUCE   1
  3. #include <dos.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <math.h>
  7. #include <string.h>
  8.  
  9. #include "jinclude.h"
  10. #include "hicolor.h"
  11. #include "viewer.h"
  12. #include "dither.h"
  13. #include "pc.h"
  14. #include "dir.h"
  15. #include "gppconio.h"
  16. #ifdef OLD_DRIVERS
  17. #include "graphics.h"
  18. #else
  19. #include "grx.h"
  20. #include "grdriver.h"
  21. #endif
  22.  
  23. /*
  24.  * Include file for declaring JPEG data structures.
  25.  * This file also includes some system headers like <stdio.h>;
  26.  * if you prefer, you can include "jconfig.h" and "jpegdata.h" instead.
  27.  */
  28.  
  29.  
  30. void targa_input_init (compress_info_ptr cinfo);
  31.  
  32. /*  GLOBALS  */
  33. ulong *Buffer0, *Buffer1, *Buffer2;    /* buffer to hold one row of pixels */
  34. BYTE ColorLUT[257];
  35. BYTE ColorLUT256[257];
  36. WORD *DispBuf;
  37. char *DispBuf256;
  38. int NewTotal;            /* */
  39. int XOffset, YOffset;
  40. int filerow, endrow, scrrow;
  41. int BytesPerPixel;
  42. long bytesPerRow;
  43. ulong lOffset;
  44. ulong Ytotal;
  45. ulong Yratio, Xratio, InvYratio, InvXratio;
  46. int width;            /* number of pixels to display in a row */
  47. int height;
  48.  
  49. int sameaspectF;
  50. int scaleF, interpF, isbottomupF, ditherF, GinterpF, hicolorF, nohicolor, twopassF,
  51.  blocksmoothF, pixelsmoothF, debugF;
  52. int F1024, F800, F640, hi800F, hi640F;
  53.  
  54. IMAGE_FORMATS FormatFlag = FMT_JFIF;    /* image file format */
  55. double Gamma;            /* exponent for contrast stretch */
  56. DCtrlType DitherCtrl;
  57. char PB[512];
  58. Files moh_files[MAXFILES];
  59. int totalfiles = 0;
  60. #ifdef OLD_DRIVERS
  61. #else
  62. GR_DRIVER_MODE_ENTRY far *ttab, *gtab;
  63. #endif
  64. extern JSAMPARRAY gifcolormap;
  65. /*
  66.  * <setjmp.h> is used for the optional error recovery mechanism shown in
  67.  * the second part of the example.
  68.  */
  69.  
  70. #include <setjmp.h>
  71. /******************** JPEG DECOMPRESSION SAMPLE INTERFACE *******************/
  72.  
  73. /* This half of the example shows how to read data from the JPEG decompressor.
  74.  * It's a little more refined than the above in that we show how to do your
  75.  * own error recovery.  If you don't care about that, you don't need these
  76.  * next two routines.
  77.  */
  78.  
  79.  
  80. /*
  81.  * These routines replace the default trace/error routines included with the
  82.  * JPEG code.  The example trace_message routine shown here is actually the
  83.  * same as the standard one, but you could modify it if you don't want messages
  84.  * sent to stderr.  The example error_exit routine is set up to return
  85.  * control to read_JPEG_file() rather than calling exit().  You can use the
  86.  * same routines for both compression and decompression error recovery.
  87.  */
  88.  
  89. /* These static variables are needed by the error routines. */
  90. static jmp_buf setjmp_buffer;    /* for return to caller */
  91. static external_methods_ptr emethods;    /* needed for access to message_parm */
  92.  
  93.  
  94. /* This routine is used for any and all trace, debug, or error printouts
  95.  * from the JPEG code.  The parameter is a printf format string; up to 8
  96.  * integer data values for the format string have been stored in the
  97.  * message_parm[] field of the external_methods struct.
  98.  */
  99.  
  100. METHODDEF void
  101. trace_message (const char *msgtext)
  102. {
  103.   fprintf (stderr, msgtext,
  104.        emethods->message_parm[0], emethods->message_parm[1],
  105.        emethods->message_parm[2], emethods->message_parm[3],
  106.        emethods->message_parm[4], emethods->message_parm[5],
  107.        emethods->message_parm[6], emethods->message_parm[7]);
  108.   fprintf (stderr, "\n");    /* there is no \n in the format string! */
  109. }
  110. /*
  111.  * The error_exit() routine should not return to its caller.  The default
  112.  * routine calls exit(), but here we assume that we want to return to
  113.  * read_JPEG_data, which has set up a setjmp context for the purpose.
  114.  * You should make sure that the free_all method is called, either within
  115.  * error_exit or after the return to the outer-level routine.
  116.  */
  117.  
  118. METHODDEF void
  119. error_exit (const char *msgtext)
  120. {
  121.   trace_message (msgtext);    /* report the error message */
  122.   (*emethods->free_all) ();    /* clean up memory allocation & temp files */
  123.   longjmp (setjmp_buffer, 1);    /* return control to outer routine */
  124. }
  125.  
  126.  
  127.  
  128. /*
  129.  * To accept the image data from decompression, you must define four routines
  130.  * output_init, put_color_map, put_pixel_rows, and output_term.
  131.  *
  132.  * You must understand the distinction between full color output mode
  133.  * (N independent color components) and colormapped output mode (a single
  134.  * output component representing an index into a color map).  You should use
  135.  * colormapped mode to write to a colormapped display screen or output file.
  136.  * Colormapped mode is also useful for reducing grayscale output to a small
  137.  * number of gray levels: when using the 1-pass quantizer on grayscale data,
  138.  * the colormap entries will be evenly spaced from 0 to MAX_JSAMPLE, so you
  139.  * can regard the indexes are directly representing gray levels at reduced
  140.  * precision.  In any other case, you should not depend on the colormap
  141.  * entries having any particular order.
  142.  * To get colormapped output, set cinfo->quantize_colors to TRUE and set
  143.  * cinfo->desired_number_of_colors to the maximum number of entries in the
  144.  * colormap.  This can be done either in your main routine or in
  145.  * d_ui_method_selection.  For grayscale quantization, also set
  146.  * cinfo->two_pass_quantize to FALSE to ensure the 1-pass quantizer is used
  147.  * (presently this is the default, but it may not be so in the future).
  148.  *
  149.  * The output file writing modules (jwrppm.c, jwrgif.c, jwrtarga.c, etc) may be
  150.  * useful examples of what these routines should actually do, although each of
  151.  * them is encrusted with a lot of specialized code for its own file format.
  152.  */
  153. void
  154. MakeColorLUT (
  155.            BYTE * pLut,    /* array to hold LUT */
  156.            BYTE minIn,    /* minimum input intensity */
  157.            BYTE maxIn,    /* maximum input intensity */
  158.            BYTE minOut,    /* minimum output intensity */
  159.            BYTE maxOut,    /* maximum output intensity */
  160.            double gamma    /* exponent of stretch */
  161. )
  162. {
  163.   int index;            /* LUT index */
  164.   double scale;            /* scale factor (K) */
  165.   double lutVal;        /* LUT value */
  166.  
  167.   scale = (maxOut - minOut) / pow (maxIn - minIn, gamma);
  168.   for (index = minIn; index <= maxIn; index++)
  169.     {
  170.       lutVal = minOut + scale * pow (index - minIn, gamma);
  171.       *pLut++ = (BYTE) (lutVal + 0.5);
  172.     }
  173. }
  174.  
  175.  
  176. METHODDEF void
  177. output_init (decompress_info_ptr cinfo)
  178. /* This routine should do any setup required */
  179. {
  180.   /* This routine can initialize for output based on the data passed in
  181.      cinfo. Useful fields include: image_width, image_height    Pretty
  182.      obvious, I hope. data_precision            bits per pixel value;
  183.      typically 8. out_color_space            output colorspace
  184.      previously requested color_out_comps            number of
  185.      color components in same final_out_comps            number of
  186.      components actually output final_out_comps is 1 if quantize_colors is
  187.      true, else it is equal to color_out_comps.
  188.  
  189.   If you have requested color quantization, the colormap is NOT yet set. You
  190.      may wish to defer output initialization until put_color_map is called. */
  191.  
  192.   int mode = 0x30;
  193.   int w, h;
  194.   ulong *b0, *b1, *b2;
  195.   int i, j, k;
  196.   int numcolors, scrwidth, scrheight;
  197.  
  198.  
  199.  
  200.   if (hicolorF)
  201.     {
  202.       numcolors = 32768;
  203.       BytesPerPixel = 2;
  204.       scrwidth = 640;
  205.       scrheight = 480;
  206.       if ((cinfo->image_width > 640 || cinfo->image_height > 480) && hi800F)
  207.     {
  208.       scrwidth = 800;
  209.       scrheight = 600;
  210.     }
  211.     }
  212.   else
  213.     {
  214.       numcolors = 256;
  215.       BytesPerPixel = 1;
  216.       scrwidth = 640;
  217.       scrheight = 480;
  218.       if ((cinfo->image_width > 640 || cinfo->image_height > 480) && F800)
  219.     {
  220.       scrwidth = 800;
  221.       scrheight = 600;
  222.     }
  223.       if ((cinfo->image_width > 800 || cinfo->image_height > 600) && F1024)
  224.     {
  225.       scrwidth = 1024;
  226.       scrheight = 768;
  227.     }
  228.     }
  229.   bytesPerRow = scrwidth * BytesPerPixel;
  230.   interpF = GinterpF;
  231.   NewTotal = 0;
  232.   Ytotal = 0;
  233.   XOffset = YOffset = 0;
  234.   scrrow = 0;
  235.   filerow = 0;
  236.   Xratio = Yratio = (1L << InflateBase);
  237.   InvXratio = InvYratio = (1L << InflateBase);
  238.   w = cinfo->image_width;
  239.   h = cinfo->image_height;
  240.   if (w > scrwidth)
  241.     {
  242.       Xratio = (w << InflateBase) / (scrwidth);
  243.       InvXratio = (scrwidth << InflateBase) / w;
  244.     }
  245.  
  246.   if (h > scrheight)
  247.     {
  248.       Yratio = (h << InflateBase) / (scrheight);
  249.       InvYratio = (scrheight << InflateBase) / h;
  250.     }
  251.   if (sameaspectF)
  252.     {
  253.       if (Yratio > Xratio)
  254.     {
  255.       Xratio = Yratio;
  256.       InvXratio = InvYratio;
  257.     }
  258.       else
  259.     {
  260.       Yratio = Xratio;
  261.       InvYratio = InvXratio;
  262.     }
  263.     }
  264.   if (!scaleF)
  265.     {
  266.       Xratio = Yratio = (1L << InflateBase);
  267.       InvXratio = InvYratio = (1L << InflateBase);
  268.     }
  269.  
  270.   w = cinfo->image_width * InvXratio;
  271.   h = cinfo->image_height * InvYratio;
  272.   if (w % (1L << InflateBase))
  273.     {
  274.       w = w >> InflateBase;
  275.       w++;
  276.     }
  277.   else
  278.     w = w >> InflateBase;
  279.   if (h % (1L << InflateBase))
  280.     {
  281.       h = h >> InflateBase;
  282.       h++;
  283.     }
  284.   else
  285.     h = h >> InflateBase;
  286.  
  287.   width = (cinfo->image_width * InvXratio) >> InflateBase;
  288.   height = (cinfo->image_width * InvYratio) >> InflateBase;
  289.  
  290.   if (w <= scrwidth)
  291.     XOffset = (scrwidth - w) / 2;
  292.   if (h <= scrheight)
  293.     YOffset = (scrheight - h) / 2;
  294.  
  295.   lOffset = 0xd0200000 + (ulong) YOffset *bytesPerRow + XOffset * BytesPerPixel;
  296.  
  297.  
  298.   endrow = Yratio >> InflateBase;
  299.  
  300.   if (Xratio == (1L << InflateBase) && Yratio == (1L << InflateBase))
  301.     interpF = 0;
  302.  
  303.   if (cinfo->total_passes == IS_BOTTOM_UP)
  304.     {                /* ### kludge for bottom up
  305.                                      targa files */
  306.       lOffset += h * bytesPerRow;
  307.       bytesPerRow = -bytesPerRow;
  308.     }
  309.  
  310.   b0 = Buffer0 = (ulong *) jget_small (sizeof (ulong) * cinfo->image_width);
  311.   b1 = Buffer1 = (ulong *) jget_small (sizeof (ulong) * cinfo->image_width);
  312.   b2 = Buffer2 = (ulong *) jget_small (sizeof (ulong) * cinfo->image_width);
  313.   for (i = 0; i < cinfo->image_width; i++)
  314.     *b0++ = *b1++ = *b2++ = 0;
  315.  
  316.   DispBuf = (WORD *) jget_small (sizeof (WORD) * cinfo->image_width);
  317.   DispBuf256 = (char *) jget_small (sizeof (char) * cinfo->image_width);
  318.  
  319.   if (ditherF)
  320.     if (interpF)
  321.       DitherInit (0, 255, 0, 31, width, &DitherCtrl);
  322.     else
  323.       DitherInit (0, 255, 0, 31, cinfo->image_width, &DitherCtrl);
  324.  
  325.   if (debugF)
  326.     {
  327.       printf ("image : %ld x %ld \n", cinfo->image_width, cinfo->image_height);
  328.       printf ("screen %dx%d\n", scrwidth, scrheight);
  329.       printf ("Xratio: %ld  Yratio: %ld\n", Xratio, Yratio);
  330.       printf ("InvXratio: %ld  InvYratio: %ld\n", InvXratio, InvYratio);
  331.       printf ("screen width %d\n", width);
  332.       if (interpF)
  333.     printf ("interpolating output\n");
  334.       else
  335.     printf ("Not interpolating output\n");
  336.       if (ditherF)
  337.     printf ("dithering output\n");
  338.       else
  339.     printf ("Not dithering output\n");
  340.       printf ("out color space: %d\n", (int) cinfo->out_color_space);
  341.  
  342.       if (getch () == 'q')
  343.     exit (0);
  344.       printf ("ok.\n");
  345.     }
  346. #ifdef OLD_DRIVERS
  347.   GrSetMode (GR_width_height_graphics,
  348.          scrwidth, scrheight);
  349. #else
  350.   GrSetMode (GR_width_height_color_graphics,
  351.          scrwidth, scrheight, numcolors);
  352. #endif
  353. /*
  354.   SetVideoMode(mode);
  355. */
  356.   /* my Tseng manual says we should be in 256 */
  357. /*
  358.   SetHicolorMode(mode);
  359. */
  360.   /* color mode before switching to hicolor */
  361.  
  362. }
  363.  
  364.  
  365. /*
  366.  * This routine is called if and only if you have set cinfo->quantize_colors
  367.  * to TRUE.  It is given the selected colormap and can complete any required
  368.  * initialization.  This call will occur after output_init and before any
  369.  * calls to put_pixel_rows.  Note that the colormap pointer is also placed
  370.  * in a cinfo field, whence it can be used by put_pixel_rows or output_term.
  371.  * num_colors will be less than or equal to desired_number_of_colors.
  372.  *
  373.  * The colormap data is supplied as a 2-D array of JSAMPLEs, indexed as
  374.  *        JSAMPLE colormap[component][indexvalue]
  375.  * where component runs from 0 to cinfo->color_out_comps-1, and indexvalue
  376.  * runs from 0 to num_colors-1.  Note that this is actually an array of
  377.  * pointers to arrays rather than a true 2D array, since C does not support
  378.  * variable-size multidimensional arrays.
  379.  * JSAMPLE is typically typedef'd as "unsigned char".  If you want your code
  380.  * to be as portable as the JPEG code proper, you should always access JSAMPLE
  381.  * values with the GETJSAMPLE() macro, which will do the right thing if the
  382.  * machine has only signed chars.
  383.  */
  384.  
  385. METHODDEF void
  386. put_color_map (decompress_info_ptr cinfo, int num_colors, JSAMPARRAY colormap)
  387. /* Write the color map */
  388. {
  389.  
  390.   int i;
  391.   JSAMPROW ptr0, ptr1, ptr2;
  392.   /* You need not provide this routine if you always set
  393.      cinfo->quantize_colors FALSE; but a safer practice is to provide it and
  394.      have it just print an error message, like this: */
  395. /*
  396.   fprintf(stderr, "put_color_map called: there's a bug here somewhere!\n");
  397. */
  398.   ptr0 = colormap[0];
  399.   if (cinfo->out_color_space == CS_RGB)
  400.     {
  401.       ptr1 = colormap[1];
  402.       ptr2 = colormap[2];
  403.     }
  404.   else
  405.     ptr1 = ptr2 = ptr0;
  406.  
  407.   for (i = 0; i < num_colors; i++)
  408.     GrSetColor (i, ColorLUT256[*(ptr0++)],
  409.         ColorLUT256[*(ptr1++)], ColorLUT256[*(ptr2++)]);
  410. }
  411.  
  412.  
  413. /*
  414.  * This function is called repeatedly, with a few more rows of pixels supplied
  415.  * on each call.  With the current JPEG code, some multiple of 8 rows will be
  416.  * passed on each call except the last, but it is extremely bad form to depend
  417.  * on this.  You CAN assume num_rows > 0.
  418.  * The data is supplied in top-to-bottom row order (the standard order within
  419.  * a JPEG file).  If you cannot readily use the data in that order, you'll
  420.  * need an intermediate array to hold the image.  See jwrrle.c for an example
  421.  * of outputting data in bottom-to-top order.
  422.  *
  423.  * The data is supplied as a 3-D array of JSAMPLEs, indexed as
  424.  *        JSAMPLE pixel_data[component][row][column]
  425.  * where component runs from 0 to cinfo->final_out_comps-1, row runs from 0 to
  426.  * num_rows-1, and column runs from 0 to cinfo->image_width-1 (column 0 is
  427.  * left edge of image).  Note that this is actually an array of pointers to
  428.  * pointers to arrays rather than a true 3D array, since C does not support
  429.  * variable-size multidimensional arrays.
  430.  * JSAMPLE is typically typedef'd as "unsigned char".  If you want your code
  431.  * to be as portable as the JPEG code proper, you should always access JSAMPLE
  432.  * values with the GETJSAMPLE() macro, which will do the right thing if the
  433.  * machine has only signed chars.
  434.  *
  435.  * If quantize_colors is true, then there is only one component, and its values
  436.  * are indexes into the previously supplied colormap.  Otherwise the values
  437.  * are actual data in your selected output colorspace.
  438.  */
  439.  
  440. #define SRED     GETJSAMPLE(*ptr0)
  441. #define SGREEN   GETJSAMPLE(*ptr1)
  442. #define SBLUE    GETJSAMPLE(*ptr2)
  443.  
  444.  
  445.  
  446. METHODDEF void
  447. put_pixel_rows256 (decompress_info_ptr cinfo, int num_rows,
  448.            JSAMPIMAGE pixel_data)
  449. {
  450.   int col, row;
  451.   JSAMPROW ptr0;
  452.  
  453.  
  454.  
  455.  
  456.   for (row = 0; row < num_rows; row++)
  457.     {
  458.       if (Ytotal <= (NewTotal + (1L << InflateBase)))
  459.     {
  460.  
  461.       ptr0 = pixel_data[0][row];
  462.       if (Xratio != (1L << InflateBase))
  463.         {
  464.           for (col = 0; col < cinfo->image_width; col++)
  465.         {
  466.           DispBuf256[(col * InvXratio + (1L << (InflateBase - 1))) >> InflateBase] =
  467.             *ptr0;
  468.           ptr0++;
  469.         }
  470.           memcpy ((char *) lOffset, DispBuf256, BytesPerPixel * width);
  471.         }            /* for col */
  472.       else
  473.         memcpy ((char *) lOffset, ptr0, BytesPerPixel * width);
  474.  
  475.  
  476.       lOffset += (long) bytesPerRow;
  477.  
  478.  
  479. /*
  480.  
  481.       PutVideoRow30H(NewTotal + YOffset, XOffset, width, DispBuf);
  482. */
  483.       NewTotal += (1L << InflateBase);
  484.       Ytotal += Yratio;
  485.     }
  486.       else
  487.     Ytotal -= (1L << InflateBase);
  488.  
  489.     }                /* for row */
  490. }
  491.  
  492.  
  493.  
  494. METHODDEF void
  495. put_pixel_rows (decompress_info_ptr cinfo, int num_rows,
  496.         JSAMPIMAGE pixel_data)
  497. /* Write some rows of output data */
  498. {
  499.   /* This example shows how you might write full-color RGB data (3
  500.      components) to an output file in which the data is stored 3 bytes per
  501.      pixel. */
  502.   JSAMPROW ptr0, ptr1, ptr2;
  503.   ulong *b0, *b1, *b2;
  504.   int col;
  505.   int row;
  506.   int newrow, mycol;
  507.   ulong temp0, temp1, temp2;
  508.   int endcol, scrcol;
  509.   char r, g, b;
  510.   register
  511.   WORD *pBuf;            /* pointer to video row buffer */
  512.   WORD w0, w1, w2;
  513.   ulong rowfrac, colfrac;
  514.  
  515. /*
  516. printf("got into put_pixel_rows\n");
  517. */
  518.  
  519.   for (row = 0; row < num_rows; row++)
  520.     {
  521.       if (interpF)
  522.     {
  523.       ptr0 = pixel_data[0][row];
  524.       if (cinfo->out_color_space == CS_RGB)
  525.         {
  526.           ptr1 = pixel_data[1][row];
  527.           ptr2 = pixel_data[2][row];
  528.         }
  529.       else
  530.         ptr1 = ptr2 = ptr0;
  531.       b0 = Buffer0;
  532.       b1 = Buffer1;
  533.       b2 = Buffer2;
  534. /*
  535. printf("filrow: %d endrow: %d\n",filerow,endrow);
  536. */
  537. /*
  538. printf("starting as: %d\n",*ptr0);
  539. */
  540.       if (filerow == endrow)
  541.         {
  542.           endrow = ((scrrow + 2) * Yratio) >> InflateBase;
  543.           rowfrac = ((scrrow + 1) << InflateBase) - filerow * InvYratio;
  544.           for (col = 0; col < cinfo->image_width; col++)
  545.         {
  546.           *b0 += rowfrac * SRED;
  547.           *b1 += rowfrac * SGREEN;
  548.           *b2 += rowfrac * SBLUE;
  549.           b0++;
  550.           b1++;
  551.           b2++;
  552.           ptr0++;
  553.           ptr1++;
  554.           ptr2++;
  555.         }
  556. /*
  557. printf("after row interp: %u\n",*Buffer0);
  558. */
  559.           ptr0 = pixel_data[0][row];
  560.           if (cinfo->out_color_space == CS_RGB)
  561.         {
  562.           ptr1 = pixel_data[1][row];
  563.           ptr2 = pixel_data[2][row];
  564.         }
  565.           else
  566.         ptr1 = ptr2 = ptr0;
  567.           b0 = Buffer0;
  568.           b1 = Buffer1;
  569.           b2 = Buffer2;
  570.           rowfrac = InvYratio - rowfrac;
  571.           endcol = Xratio >> InflateBase;
  572.           scrcol = 0;
  573.           temp0 = temp1 = temp2 = 0;
  574.           for (col = 0; col < cinfo->image_width; col++)
  575.         {
  576.           if (col == endcol)
  577.             {
  578.               endcol = ((scrcol + 2) * Xratio) >> InflateBase;
  579.               colfrac = ((ulong) (scrcol + 1) << InflateBase) - (col * InvXratio);
  580.               temp0 += colfrac * ((*b0 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
  581.               temp1 += colfrac * ((*b1 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
  582.               temp2 += colfrac * ((*b2 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
  583. /*
  584. if (col==1) printf("after col frac: %u wih colfrac %u\n",temp0,colfrac);
  585. */
  586.  
  587.  
  588.               if (!ditherF)
  589.             DispBuf[scrcol] =
  590.               (((WORD) (ColorLUT[(temp0 + (1L << (ColorBase - 1))) >> ColorBase])) << 10 |
  591.                ((WORD) (ColorLUT[(temp1 + (1L << (ColorBase - 1))) >> ColorBase])) << 5 |
  592.                (WORD) (ColorLUT[(temp2 + (1L << (ColorBase - 1))) >> ColorBase]));
  593.               else
  594.             {
  595.               Buffer0[scrcol] = ColorLUT256[(temp0 + (1L << (ColorBase - 1))) >> ColorBase];
  596.               Buffer1[scrcol] = ColorLUT256[(temp1 + (1L << (ColorBase - 1))) >> ColorBase];
  597.               Buffer2[scrcol] = ColorLUT256[(temp2 + (1L << (ColorBase - 1))) >> ColorBase];
  598.             }
  599.  
  600.               colfrac = InvXratio - colfrac;
  601.               temp0 = colfrac * ((*b0 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
  602.               temp1 = colfrac * ((*b1 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
  603.               temp2 = colfrac * ((*b2 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
  604.               scrcol++;
  605.             }
  606.           else
  607.             {
  608.               temp0 += InvXratio * ((*b0 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
  609.               temp1 += InvXratio * ((*b1 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
  610.               temp2 += InvXratio * ((*b2 + (1L << (InflateBase - BaseDiff - 1))) >> (InflateBase - BaseDiff));
  611. /*
  612. if (!col) printf("after col add: %u\n",temp0);
  613. */
  614.             }
  615.  
  616.           *b0++;
  617.           *b1++;
  618.           *b2++;
  619.           ptr0++;
  620.           ptr1++;
  621.           ptr2++;
  622.         }
  623. /*
  624. printf("after col interp: %u\n",*Buffer0);
  625.  
  626. */
  627.  
  628.           if (ditherF)
  629.         {
  630.           Dither (&DitherCtrl, Buffer0, Buffer0, scrrow % 2);
  631.           Dither (&DitherCtrl, Buffer1, Buffer1, scrrow % 2);
  632.           Dither (&DitherCtrl, Buffer2, Buffer2, scrrow % 2);
  633.           for (col = 0; col < width; col++)
  634.             DispBuf[col] = ((WORD) Buffer0[col] << 10) |
  635.               ((WORD) Buffer1[col] << 5) |
  636.               ((WORD) Buffer2[col]);
  637.         }
  638.  
  639.  
  640.           memcpy ((char *) lOffset, DispBuf, BytesPerPixel * width);
  641.           lOffset += (long) bytesPerRow;
  642.           scrrow++;
  643.  
  644.           b0 = Buffer0;
  645.           b1 = Buffer1;
  646.           b2 = Buffer2;
  647.           ptr0 = pixel_data[0][row];
  648.           if (cinfo->out_color_space == CS_RGB)
  649.         {
  650.           ptr1 = pixel_data[1][row];
  651.           ptr2 = pixel_data[2][row];
  652.         }
  653.           else
  654.         ptr1 = ptr2 = ptr0;
  655.           for (col = 0; col < cinfo->image_width; col++)
  656.         {
  657.           *b0++ = rowfrac * SRED;
  658.           *b1++ = rowfrac * SGREEN;
  659.           *b2++ = rowfrac * SBLUE;
  660.           ptr0++;
  661.           ptr1++;
  662.           ptr2++;
  663.         }
  664.  
  665.         }
  666.       else
  667.         {
  668.           for (col = 0; col < cinfo->image_width; col++)
  669.         {
  670.           *b0 += InvYratio * SRED;
  671.           *b1 += InvYratio * SGREEN;
  672.           *b2 += InvYratio * SBLUE;
  673.           b0++;
  674.           b1++;
  675.           b2++;
  676.           ptr0++;
  677.           ptr1++;
  678.           ptr2++;
  679.         }
  680. /*
  681. printf("after row add: %u\n",*Buffer0);
  682. */
  683.         }
  684.       filerow++;
  685.  
  686.  
  687.     }
  688.       else if (Ytotal <= (NewTotal + (1L << InflateBase)))
  689.     {
  690.  
  691.  
  692.       ptr0 = pixel_data[0][row];
  693.       if (cinfo->out_color_space == CS_RGB)
  694.         {
  695.           ptr1 = pixel_data[1][row];
  696.           ptr2 = pixel_data[2][row];
  697.         }
  698.       else
  699.         ptr1 = ptr2 = ptr0;
  700.       if (ditherF)
  701.         {
  702.           DitherChar (&DitherCtrl, ptr0, ptr0, (NewTotal >> InflateBase) % 2);
  703.           DitherChar (&DitherCtrl, ptr1, ptr1, (NewTotal >> InflateBase) % 2);
  704.           DitherChar (&DitherCtrl, ptr2, ptr2, (NewTotal >> InflateBase) % 2);
  705.           for (col = 0; col < cinfo->image_width; col++)
  706.         DispBuf[(col * InvXratio + (1L << (InflateBase - 1))) >> InflateBase] =
  707.           ((WORD) ptr0[col] << 10) |
  708.           ((WORD) ptr1[col] << 5) |
  709.           ((WORD) ptr2[col]);
  710.         }
  711.       else
  712.         for (col = 0; col < cinfo->image_width; col++)
  713.           {
  714.         DispBuf[(col * InvXratio + (1L << (InflateBase - 1))) >> InflateBase] =
  715.           (((WORD) (ColorLUT[SRED])) << 10 |
  716.            ((WORD) (ColorLUT[SGREEN])) << 5 |
  717.            (WORD) (ColorLUT[SBLUE]));
  718.         ptr0++;
  719.         ptr1++;
  720.         ptr2++;
  721.  
  722.           }            /* for */
  723.  
  724.  
  725.       /* calculate video page and offset */
  726.  
  727.  
  728.       memcpy ((char *) lOffset, DispBuf, BytesPerPixel * width);
  729.       lOffset += (long) bytesPerRow;
  730.  
  731.  
  732. /*
  733.  
  734.       PutVideoRow30H(NewTotal + YOffset, XOffset, width, DispBuf);
  735. */
  736.       NewTotal += (1L << InflateBase);
  737.       Ytotal += Yratio;
  738.     }
  739.       else
  740.     Ytotal -= (1L << InflateBase);
  741.     }
  742. }
  743.  
  744.  
  745.  
  746. METHODDEF void
  747. output_term (decompress_info_ptr cinfo)
  748. /* Finish up at the end of the output */
  749. {
  750.   /* This termination routine may not need to do anything. */
  751.   /* Note that the JPEG code will only call it during successful exit; */
  752.  
  753.   /* if you want it called during error exit, you gotta do that yourself. */
  754.   DitherTerm (&DitherCtrl);
  755.   (*cinfo->emethods->free_all) ();
  756.  
  757. }
  758.  
  759.  
  760. /*
  761.  * That's it for the routines that deal with writing the output image.
  762.  * Now we have overall control and parameter selection routines.
  763.  */
  764.  
  765.  
  766. /*
  767.  * This routine gets control after the JPEG file header has been read;
  768.  * at this point the image size and colorspace are known.
  769.  * The routine must determine what output routines are to be used, and make
  770.  * any decompression parameter changes that are desirable.  For example,
  771.  * if it is found that the JPEG file is grayscale, you might want to do
  772.  * things differently than if it is color.  You can also delay setting
  773.  * quantize_colors and associated options until this point.
  774.  *
  775.  * j_d_defaults initializes out_color_space to CS_RGB.  If you want grayscale
  776.  * output you should set out_color_space to CS_GRAYSCALE.  Note that you can
  777.  * force grayscale output from a color JPEG file (though not vice versa).
  778.  */
  779.  
  780. METHODDEF void
  781. d_ui_method_selection (decompress_info_ptr cinfo)
  782. {
  783.   /* if grayscale input, force grayscale output; */
  784.   /* else leave the output colorspace as set by main routine. */
  785.   if (cinfo->jpeg_color_space == CS_GRAYSCALE)
  786.     cinfo->out_color_space = CS_GRAYSCALE;
  787.  
  788.   /* select output routines */
  789.   cinfo->methods->output_init = output_init;
  790.   cinfo->methods->put_color_map = put_color_map;
  791.   if (hicolorF)
  792.     cinfo->methods->put_pixel_rows = put_pixel_rows;
  793.   else
  794.     cinfo->methods->put_pixel_rows = put_pixel_rows256;
  795.   cinfo->methods->output_term = output_term;
  796. }
  797.  
  798.  
  799. /*
  800.  * OK, here is the main function that actually causes everything to happen.
  801.  * We assume here that the JPEG filename is supplied by the caller of this
  802.  * routine, and that all decompression parameters can be default values.
  803.  * The routine returns 1 if successful, 0 if not.
  804.  */
  805.  
  806. GLOBAL int
  807. read_JPEG_file (char *filename)
  808. {
  809.   /* These three structs contain JPEG parameters and working data. They must
  810.      survive for the duration of parameter setup and one call to
  811.      jpeg_decompress; typically, making them local data in the calling
  812.      routine is the best strategy. */
  813.   struct decompress_info_struct cinfo;
  814.   struct decompress_methods_struct dc_methods;
  815.   struct external_methods_struct e_methods;
  816.   /* Select the input and output files. In this example we want to open the
  817.      input file before doing anything else, so that the setjmp() error
  818.      recovery below can assume the file is open. Note that cinfo.output_file
  819.      is only used if your output handling routines use it; otherwise, you can
  820.      just make it NULL. VERY IMPORTANT: use "b" option to fopen() if you are
  821.      on a machine that requires it in order to read binary files. */
  822.  
  823.   if ((cinfo.input_file = fopen (filename, "rb")) == NULL)
  824.     {
  825.       fprintf (stderr, "can't open %s\n", filename);
  826.       return 0;
  827.     }
  828.   cinfo.output_file = NULL;    /* if no actual output file involved */
  829.  
  830.   /* Initialize the system-dependent method pointers. */
  831.   cinfo.methods = &dc_methods;    /* links to method structs */
  832.   cinfo.emethods = &e_methods;
  833.   /* Here we supply our own error handler; compare to use of standard error
  834.      handler in the previous write_JPEG_file example. */
  835.   emethods = &e_methods;    /* save struct addr for possible access */
  836.   e_methods.trace_level = 0;
  837.   e_methods.error_exit = error_exit;    /* supply error-exit routine */
  838.   e_methods.trace_message = trace_message;    /* supply trace-message
  839.                            routine */
  840.  
  841.   /* prepare setjmp context for possible exit from error_exit */
  842.   if (setjmp (setjmp_buffer))
  843.     {
  844.       /* If we get here, the JPEG code has signaled an error. Memory allocation
  845.          has already been cleaned up (see free_all call in error_exit), but we
  846.          need to close the input file before returning. You might also need to
  847.          close an output file, etc. */
  848.       fclose (cinfo.input_file);
  849.       return 0;
  850.     }
  851.   /* Here we use the standard memory manager provided with the JPEG code. In
  852.      some cases you might want to replace the memory manager, or at least the
  853.      system-dependent part of it, with your own code. */
  854.   jselmemmgr (&e_methods);    /* select std memory allocation routines */
  855.   /* If the decompressor requires full-image buffers (for two-pass color
  856.      quantization or a noninterleaved JPEG file), it will create temporary
  857.      files for anything that doesn't fit within the maximum-memory setting.
  858.      You can change the default maximum-memory setting by changing
  859.      e_methods.max_memory_to_use after jselmemmgr returns. On some systems
  860.      you may also need to set up a signal handler to ensure that temporary
  861.      files are deleted if the program is interrupted. (This is most important
  862.      if you are on MS-DOS and use the jmemdos.c memory manager back end; it
  863.      will try to grab extended memory for temp files, and that space will NOT
  864.      be freed automatically.) See jcmain.c or jdmain.c for an example signal
  865.      handler. */
  866.  
  867.   /* Here, set up the pointer to your own routine for post-header-reading
  868.      parameter selection.  You could also initialize the pointers to the
  869.      output data handling routines here, if they are not dependent on the
  870.      image type. */
  871.   dc_methods.d_ui_method_selection = d_ui_method_selection;
  872.  
  873.   /* Set up default decompression parameters. */
  874.   j_d_defaults (&cinfo, TRUE);
  875.   /* TRUE indicates that an input buffer should be allocated. In unusual
  876.      cases you may want to allocate the input buffer yourself; see jddeflts.c
  877.      for commentary. */
  878.  
  879.   /* At this point you can modify the default parameters set by j_d_defaults
  880.      as needed; for example, you can request color quantization or force
  881.      grayscale output.  See jdmain.c for examples of what you might change. */
  882.  
  883.   if (!hicolorF)
  884.     {
  885.       cinfo.quantize_colors = TRUE;
  886.       if (twopassF)
  887.     cinfo.two_pass_quantize = TRUE;
  888.       else
  889.     cinfo.two_pass_quantize = FALSE;
  890.     }
  891.   if (blocksmoothF)
  892.     cinfo.do_block_smoothing = TRUE;
  893.   if (pixelsmoothF)
  894.     cinfo.do_pixel_smoothing = TRUE;
  895.  
  896.  
  897.   /* Set up to read a JFIF or baseline-JPEG file. */
  898.   /* This is the only JPEG file format currently supported. */
  899.   jselrjfif (&cinfo);
  900.  
  901.   /* Here we go! */
  902.   jpeg_decompress (&cinfo);
  903.  
  904.   /* That's it, son.  Nothin' else to do, except close files. */
  905.   /* Here we assume only the input file need be closed. */
  906.   fclose (cinfo.input_file);
  907.  
  908.   return 1;            /* indicate success */
  909.  
  910.   /* Note: if you want to decompress more than one image, we recommend you
  911.      repeat this whole routine.  You MUST repeat the j_d_defaults()/alter
  912.      parameters/jpeg_decompress() sequence, as some data structures allocated
  913.      in j_d_defaults are freed upon exit from jpeg_decompress. */
  914. }
  915.  
  916. void
  917. read_TARGA_file (char *name)
  918. {
  919.   struct compress_info_struct moh_cinfo;
  920.   struct decompress_info_struct moh_dcinfo;
  921.   struct compress_methods_struct moh_c_methods;
  922.   struct external_methods_struct moh_e_methods;
  923.  
  924.   JSAMPARRAY pixel_row;
  925.   int i, j, k;
  926.   JSAMPIMAGE pixel_rows;
  927.  
  928. /* note the similarities here and read_JPEG_file */
  929. /* ## clearly needs modularization */
  930.  
  931.  
  932.   moh_cinfo.methods = &moh_c_methods;
  933.   moh_cinfo.emethods = &moh_e_methods;
  934.   jselerror (&moh_e_methods);    /* error/trace message routines */
  935.   jselmemmgr (&moh_e_methods);    /* memory allocation routines */
  936.  
  937.   if ((moh_cinfo.input_file = fopen (name, "rb")) == NULL)
  938.     {
  939.       fprintf (stderr, "Can't open %s\n", name);
  940.       exit (EXIT_FAILURE);
  941.     }
  942.  
  943.   jselrtarga (&moh_cinfo);
  944.  
  945.   moh_cinfo.total_passes = 0;
  946.   (*moh_cinfo.methods->input_init) (&moh_cinfo);
  947.  
  948.   /* now to copy the info into a *de*compress info struct, */
  949.   /* as put_pixel_rows & output_init require that */
  950.   /* ## I dislike this hack */
  951.  
  952.   moh_dcinfo.image_width = moh_cinfo.image_width;
  953.   moh_dcinfo.image_height = moh_cinfo.image_height;
  954.   moh_dcinfo.methods = moh_cinfo.methods;
  955.   moh_dcinfo.emethods = moh_cinfo.emethods;
  956.  
  957.   moh_dcinfo.total_passes = moh_cinfo.total_passes;
  958.   moh_dcinfo.out_color_space = CS_RGB;
  959.  
  960.   /* allolcate space for one row of data */
  961.   pixel_rows = (JSAMPIMAGE) (*moh_cinfo.emethods->alloc_small)
  962.     (3 * SIZEOF (JSAMPARRAY));
  963.   pixel_rows[0] = (JSAMPARRAY) (*moh_cinfo.emethods->alloc_small)
  964.     (MAXROWREAD * SIZEOF (JSAMPROW));
  965.   pixel_rows[1] = (JSAMPARRAY) (*moh_cinfo.emethods->alloc_small)
  966.     (MAXROWREAD * SIZEOF (JSAMPROW));
  967.   pixel_rows[2] = (JSAMPARRAY) (*moh_cinfo.emethods->alloc_small)
  968.     (MAXROWREAD * SIZEOF (JSAMPROW));
  969.   for (i = 0; i < 3; i++)
  970.     {
  971.       for (j = 0; j < MAXROWREAD; j++)
  972.     pixel_rows[i][j] = (JSAMPROW)
  973.       (*moh_cinfo.emethods->alloc_small) (moh_cinfo.image_width * sizeof (JSAMPLE));
  974.     }
  975.   pixel_row = (JSAMPARRAY) (*moh_cinfo.emethods->alloc_small)
  976.     (3 /* moh_cinfo.num_components */ * SIZEOF (JSAMPROW));
  977.   for (i = 0; i < 3 /* moh_cinfo.num_components */ ; i++)
  978.     pixel_row[i] = (JSAMPROW) (*moh_cinfo.emethods->alloc_small)
  979.       (moh_cinfo.image_width * sizeof (JSAMPLE));
  980. /*
  981.  
  982.     pixel_row=(JSAMPIMAGE) malloc(3 *sizeof(JSAMPARRAY));
  983.     for(i=0;i<3;i++)
  984.         pixel_row[i]=(JSAMPROW) malloc(sizeof(JSAMPLE)*moh_cinfo.image_width);
  985. */
  986.  
  987.   output_init (&moh_dcinfo);
  988.   for (i = moh_cinfo.image_height; i;)
  989.     {
  990.       k = MIN (i, MAXROWREAD);
  991.       i -= k;
  992.       for (j = 0; j < k; j++)
  993.     {
  994.       pixel_row[0] = pixel_rows[0][j];
  995.       pixel_row[1] = pixel_rows[1][j];
  996.       pixel_row[2] = pixel_rows[2][j];
  997.       (*moh_cinfo.methods->get_input_row) (&moh_cinfo, pixel_row);
  998.     }
  999.       put_pixel_rows (&moh_dcinfo, k, pixel_rows);
  1000.     }
  1001.   /*now to free things */
  1002.   (*moh_cinfo.emethods->free_all) ();
  1003.  
  1004.   fclose (moh_cinfo.input_file);
  1005. }
  1006.  
  1007. void
  1008. read_GIF_file (char *name)
  1009. {
  1010.   struct compress_info_struct moh_cinfo;
  1011.   struct decompress_info_struct moh_dcinfo;
  1012.   struct compress_methods_struct moh_c_methods;
  1013.   struct external_methods_struct moh_e_methods;
  1014.  
  1015.   JSAMPIMAGE pixel_row;
  1016.   JSAMPIMAGE pixel_rows;
  1017.   int i, j, k;
  1018.   int temphicolor, tempdither;
  1019.  
  1020.   temphicolor = hicolorF;
  1021.   tempdither = ditherF;
  1022.  
  1023.   hicolorF = 0;
  1024.   ditherF = 0;
  1025.  
  1026. /* note the similarities here and read_JPEG_file */
  1027. /* ## clearly needs modularization */
  1028.  
  1029.  
  1030.   moh_cinfo.methods = &moh_c_methods;
  1031.   moh_cinfo.emethods = &moh_e_methods;
  1032.   jselerror (&moh_e_methods);    /* error/trace message routines */
  1033.   jselmemmgr (&moh_e_methods);    /* memory allocation routines */
  1034.  
  1035.   if ((moh_cinfo.input_file = fopen (name, "rb")) == NULL)
  1036.     {
  1037.       fprintf (stderr, "Can't open %s\n", name);
  1038.       exit (EXIT_FAILURE);
  1039.     }
  1040.  
  1041.   jselrgif (&moh_cinfo);
  1042.  
  1043.   moh_cinfo.total_passes = 0;
  1044.   (*moh_cinfo.methods->input_init) (&moh_cinfo);
  1045.  
  1046.   /* now to copy the info into a *de*compress info struct, */
  1047.   /* as put_pixel_rows & output_init require that */
  1048.   /* ## I dislike this hack */
  1049.  
  1050.   moh_dcinfo.image_width = moh_cinfo.image_width;
  1051.   moh_dcinfo.image_height = moh_cinfo.image_height;
  1052.   moh_dcinfo.methods = moh_cinfo.methods;
  1053.   moh_dcinfo.emethods = moh_cinfo.emethods;
  1054.  
  1055.   moh_dcinfo.total_passes = moh_cinfo.total_passes;
  1056.   moh_dcinfo.out_color_space = CS_RGB;
  1057.  
  1058.   /* allolcate space for one row of data */
  1059.   pixel_row = (JSAMPIMAGE) (*moh_cinfo.emethods->alloc_small)
  1060.     (1 * SIZEOF (JSAMPARRAY));
  1061.   pixel_row[0] = (JSAMPARRAY) (*moh_cinfo.emethods->alloc_small)
  1062.     (MAXROWREAD * SIZEOF (JSAMPROW));
  1063.   pixel_row[0][0] = (JSAMPROW)
  1064.     (*moh_cinfo.emethods->alloc_small) (moh_cinfo.image_width * sizeof (JSAMPLE));
  1065.  
  1066.   output_init (&moh_dcinfo);
  1067.   put_color_map (&moh_dcinfo, 256, gifcolormap);
  1068.   for (i = moh_cinfo.image_height; i; i--)
  1069.     {
  1070.       (*moh_cinfo.methods->get_input_row) (&moh_cinfo, (JSAMPARRAY) pixel_row);
  1071.       put_pixel_rows256 (&moh_dcinfo, 1, pixel_row);
  1072.  
  1073.     }
  1074.  
  1075.   /*now to free things */
  1076.   (*moh_cinfo.emethods->free_all) ();
  1077.  
  1078.   fclose (moh_cinfo.input_file);
  1079.   hicolorF = temphicolor;
  1080.   ditherF = tempdither;
  1081.  
  1082. }
  1083.  
  1084.  
  1085.  
  1086. void
  1087. Usage ()
  1088. {
  1089.   fprintf (stderr, "Usage: hiview [options] file ...\n");
  1090.   fprintf (stderr, "   where the options are:\n");
  1091.   fprintf (stderr, "     -d   toggle Floyd-Steinberg dithering, default is off\n");
  1092.   fprintf (stderr, "     -i   toggle smooth interpolation when resizing image, default is on\n");
  1093.   fprintf (stderr, "     -g   GIF format file\n");
  1094.   fprintf (stderr, "     -t   TARGA format file\n");
  1095.   fprintf (stderr, "     -s gamma    contrast stretch using exponent gamma\n");
  1096.   fprintf (stderr, "          gamma is a positive double precision number\n");
  1097.   fprintf (stderr, "          values are typically in the range 0.5 .. 1.0\n");
  1098.   fprintf (stderr, "     -q toggle one/two pass quantization, default is one\n");
  1099.   fprintf (stderr, "     -? this message\n");
  1100.   fprintf (stderr, "     -D   Debug mode\n");
  1101.   fprintf (stderr, "   Filenames may contain wildcards\n");
  1102.   fprintf (stderr, "\n");
  1103. }
  1104.  
  1105.  
  1106. IMAGE_FORMATS
  1107. getformat (char *name)
  1108. {
  1109.   char drive[MAXDRIVE];
  1110.   char dir[MAXDIR];
  1111.   char file[MAXFILE];
  1112.   char ext[MAXEXT];
  1113.   IMAGE_FORMATS type;
  1114.  
  1115.   fnsplit (name, drive, dir, file, ext);
  1116.   if (!strcmp (ext, ".JPG"))
  1117.     type = FMT_JFIF;
  1118.   else if (!strcmp (ext, ".GIF"))
  1119.     type = FMT_GIF;
  1120.   else if (!strcmp (ext, ".TGA"))
  1121.     type = FMT_TARGA;
  1122.   else
  1123.     type = FMT_UNKNOWN;
  1124.   return (type);
  1125. }
  1126. void
  1127. getfiles (char *path, IMAGE_FORMATS ex_type, int level)
  1128. {
  1129.   struct ffblk tempfile;
  1130.   int result;
  1131.   char drive[MAXDRIVE];
  1132.   char dir[MAXDIR];
  1133.   char file[MAXFILE];
  1134.   char ext[MAXEXT];
  1135.   char newpath[500];
  1136.   IMAGE_FORMATS type;
  1137.  
  1138.   result = findfirst (path, &tempfile, 0 | FA_RDONLY | FA_DIREC);
  1139.   type = ex_type;
  1140.   while (result >= 0)
  1141.     {
  1142.       if (!(tempfile.ff_attrib & FA_DIREC))
  1143.     {
  1144.       fnsplit (path, drive, dir, file, ext);
  1145.       strcpy (moh_files[totalfiles].name, drive);
  1146.       strcat (moh_files[totalfiles].name, dir);
  1147.       strcat (moh_files[totalfiles].name, tempfile.ff_name);
  1148.       if (ex_type == FMT_UNKNOWN)
  1149.         type = getformat (moh_files[totalfiles].name);
  1150.       moh_files[totalfiles].type = type;
  1151.       moh_files[totalfiles].selected = 0;
  1152.       totalfiles++;
  1153.       result = findnext (&tempfile);
  1154.     }
  1155.       else
  1156.     {            /* find all *.jpg, gif, tga in directory */
  1157.       fnsplit (path, drive, dir, file, ext);
  1158.       strcpy (newpath, drive);
  1159.       strcat (newpath, dir);
  1160.       strcat (newpath, tempfile.ff_name);
  1161.       result = findnext (&tempfile);
  1162.     }
  1163.     }
  1164. }
  1165.  
  1166. void
  1167. parse_command (int argc, char **argv)
  1168. {
  1169.   struct ffblk tempfile;
  1170.   int result, i, filespec;
  1171.   IMAGE_FORMATS type;
  1172.   char flag;
  1173.  
  1174.   filespec = 0;
  1175.   type = FMT_UNKNOWN;
  1176.   for (i = 1; i < argc; i++)
  1177.     {
  1178.       if (*argv[i] == '-')
  1179.     {
  1180.       flag = *(argv[i] + 1);
  1181.       switch (flag)
  1182.         {
  1183.         case 't':
  1184.           type = FMT_TARGA;
  1185.           break;
  1186.         case 'g':
  1187.           type = FMT_GIF;
  1188.           break;
  1189.         case 'j':
  1190.           type = FMT_JFIF;
  1191.           break;
  1192.         case 'd':
  1193.           ditherF = !ditherF;
  1194.           break;
  1195.         case 'i':
  1196.           GinterpF = !GinterpF;
  1197.           break;
  1198.         case 's':
  1199.           Gamma = atof (argv[++i]);
  1200.           break;
  1201.         case 'h':
  1202.           hicolorF = !hicolorF;
  1203.           break;
  1204.         case 'b':
  1205.           blocksmoothF = !blocksmoothF;
  1206.           break;
  1207.         case 'p':
  1208.           pixelsmoothF = !pixelsmoothF;
  1209.           break;
  1210.         case 'q':
  1211.           twopassF = !twopassF;
  1212.           break;
  1213.         case 'D':
  1214.           debugF = 1;
  1215.           break;
  1216.         case '?':
  1217.           Usage ();
  1218.           exit (0);
  1219.           break;
  1220.  
  1221.         }
  1222.     }
  1223.       else
  1224.     {
  1225.       filespec = 1;
  1226.       getfiles (argv[i], type, 0);
  1227.     }
  1228.     }
  1229.  
  1230.   if (!filespec)
  1231.     {
  1232.       getfiles ("*.jpg", FMT_JFIF, 1);
  1233.       getfiles ("*.tga", FMT_TARGA, 1);
  1234.       getfiles ("*.gif", FMT_GIF, 1);
  1235.     }
  1236. }
  1237.  
  1238. void
  1239. draw_border ()
  1240. {
  1241.   int i;
  1242.  
  1243.   gotoxy (1, 1);
  1244.  
  1245.   textbackground (BORDER_BCOLOR);
  1246.   textcolor (BORDER_FCOLOR);
  1247.   for (i = 1; i < SC_WIDTH - 1; i++)
  1248.     cprintf (" ");
  1249.   gotoxy (34, 1);
  1250.   cprintf ("%s v.%s", PROGNAME,VERSION);
  1251.   gotoxy (1, SC_HEIGHT);
  1252.   for (i = 1; i < SC_WIDTH - 1; i++)
  1253.     cprintf (" ");
  1254.   gotoxy (1, SC_HEIGHT - 1);
  1255.   textbackground (MESSAGE_BCOLOR);
  1256.   textcolor (MESSAGE_FCOLOR);
  1257.   cprintf ("%d Files.", totalfiles);
  1258.   gotoxy (40, SC_HEIGHT - 1);
  1259.   textcolor (MESSAGE_HIGHLIGHT);
  1260.   cprintf ("O");
  1261.   textcolor (MESSAGE_FCOLOR);
  1262.   cprintf ("ptions");
  1263.  
  1264.  
  1265. }
  1266.  
  1267. void
  1268. highlight (int fileoffset, int currentpos, int on)
  1269. {
  1270.   int x, y, i, j;
  1271.   int colheight;
  1272.   char drive[MAXDRIVE];
  1273.   char dir[MAXDIR];
  1274.   char file[MAXFILE];
  1275.   char ext[MAXEXT];
  1276.  
  1277.   colheight = SC_HEIGHT - SC_HEADER - SC_FOOTER;
  1278.   x = (SC_WIDTH - SC_COLS * SC_COL_WIDTH) / 2;
  1279.   y = SC_HEADER + 1;
  1280.   i = currentpos - fileoffset;
  1281.   while (i >= colheight)
  1282.     {
  1283.       i -= colheight;
  1284.       x += SC_COL_WIDTH;
  1285.     }
  1286.   y += i;
  1287.   x -= 1;
  1288.  
  1289.   gotoxy (x, y);
  1290.   if (on)
  1291.     {
  1292.       textcolor (FILE_BCOLOR);
  1293.       textbackground (FILE_FCOLOR);
  1294.     }
  1295.   else
  1296.     {
  1297.       textbackground (FILE_BCOLOR);
  1298.       textcolor (FILE_FCOLOR);
  1299.     }
  1300.   for (i = 0; i < SC_COL_WIDTH; i++)
  1301.     cprintf (" ");
  1302.   gotoxy (x, y);
  1303.   fnsplit (moh_files[currentpos].name, drive, dir, file, ext);
  1304.  
  1305.   cprintf (" %s", file);
  1306.   gotoxy (x + 10, y);
  1307.   cprintf ("%s ", ext);
  1308.   textbackground (FILE_BCOLOR);
  1309.   textcolor (FILE_FCOLOR);
  1310.  
  1311.  
  1312.  
  1313. }
  1314.  
  1315.  
  1316.  
  1317. void
  1318. print_files (int fileoffset, int currentpos)
  1319. {
  1320.   int i, j, k;
  1321.   int x, y, lastfile;
  1322.   int onscreen;
  1323.   char drive[MAXDRIVE];
  1324.   char dir[MAXDIR];
  1325.   char myfilename[50];
  1326.   char ext[MAXEXT];
  1327.  
  1328.   onscreen = (SC_HEIGHT - SC_HEADER - SC_FOOTER) * SC_COLS;
  1329.  
  1330.   textbackground (FILE_BCOLOR);
  1331.   textcolor (FILE_FCOLOR);
  1332.  
  1333.   for (i = SC_HEADER + 1; i <= SC_HEIGHT - SC_FOOTER; i++)
  1334.     {
  1335.       gotoxy (1, i);
  1336.       clreol ();
  1337.     }
  1338.   x = (SC_WIDTH - SC_COLS * SC_COL_WIDTH) / 2;
  1339.   y = SC_HEADER + 1;
  1340.   lastfile = MIN (totalfiles, onscreen + fileoffset);
  1341.   for (i = fileoffset; i < lastfile; i++)
  1342.     {
  1343.       gotoxy (x, y);
  1344.       fnsplit (moh_files[i].name, drive, dir, myfilename, ext);
  1345.       cprintf ("%s", myfilename);
  1346.  
  1347.       gotoxy (x + 9, y);
  1348.  
  1349.       cprintf ("%s", ext);
  1350.       y++;
  1351.       if (y > SC_HEIGHT - SC_FOOTER)
  1352.     {
  1353.       x += SC_COL_WIDTH;
  1354.       y = SC_HEADER + 1;
  1355.     }
  1356.     }
  1357.   highlight (fileoffset, currentpos, 1);
  1358. }
  1359.  
  1360. double
  1361. getdouble ()
  1362. {
  1363.   double gamma;
  1364.  
  1365.   scanf ("%lf", &gamma);
  1366.   if (gamma<0) gamma=1;
  1367.   return (gamma);
  1368. }
  1369.  
  1370. void
  1371. optionsmenu ()
  1372. {
  1373.   int quitF = 0;
  1374.   int c;
  1375.  
  1376.   clrscr ();
  1377.   gotoxy (1, SC_HEADER + 1);
  1378.   textbackground (MESSAGE_BCOLOR);
  1379.   textcolor (MESSAGE_HEADER);
  1380.   cprintf ("Global Options: ");
  1381.   gotoxy (1, SC_HEADER + 2);
  1382.   textcolor (MESSAGE_HIGHLIGHT);
  1383.   cprintf ("H");
  1384.   textcolor (MESSAGE_FCOLOR);
  1385.   cprintf ("icolor: ");
  1386.   if (nohicolor)
  1387.     cprintf ("Not available.");
  1388.   else if (hicolorF)
  1389.     cprintf ("Used.");
  1390.   else
  1391.     cprintf ("Not used.");
  1392.   gotoxy (1, SC_HEADER + 3);
  1393.   textcolor (MESSAGE_HIGHLIGHT);
  1394.   cprintf ("B");
  1395.   textcolor (MESSAGE_FCOLOR);
  1396.   cprintf ("lock smoothing: ");
  1397.   if (blocksmoothF)
  1398.     cprintf ("Yes.");
  1399.   else
  1400.     cprintf ("No.");
  1401.  
  1402.   gotoxy (1, SC_HEADER + 4);
  1403.   textcolor (MESSAGE_HIGHLIGHT);
  1404.   cprintf ("P");
  1405.   textcolor (MESSAGE_FCOLOR);
  1406.   cprintf ("ixel smoothing: ");
  1407.   if (pixelsmoothF)
  1408.     cprintf ("Yes.");
  1409.   else
  1410.     cprintf ("No");
  1411.   gotoxy (1, SC_HEADER + 5);
  1412.   textcolor (MESSAGE_HIGHLIGHT);
  1413.   cprintf ("G");
  1414.   textcolor (MESSAGE_FCOLOR);
  1415.   cprintf ("amma: %0.2lf\n", Gamma);
  1416.  
  1417.   gotoxy (1, SC_HEADER + 7);
  1418.   textcolor (MESSAGE_HEADER);
  1419.   cprintf ("24->15 bit Options: ");
  1420.   gotoxy (1, SC_HEADER + 8);
  1421.   textcolor (MESSAGE_HIGHLIGHT);
  1422.   cprintf ("I");
  1423.   textcolor (MESSAGE_FCOLOR);
  1424.   cprintf ("nterpolation: ");
  1425.   if (GinterpF)
  1426.     cprintf ("Linear Averaging.\n");
  1427.   else
  1428.     cprintf ("None.\n");
  1429.   gotoxy (1, SC_HEADER + 9);
  1430.   textcolor (MESSAGE_HIGHLIGHT);
  1431.   cprintf ("D");
  1432.   textcolor (MESSAGE_FCOLOR);
  1433.   cprintf ("ithering: ");
  1434.   if (ditherF)
  1435.     cprintf ("Floyd-Steinberg.\n");
  1436.   else
  1437.     cprintf ("None.\n");
  1438.   gotoxy (1, SC_HEADER + 11);
  1439.   textcolor (MESSAGE_HEADER);
  1440.   cprintf ("24->8 bit Options: ");
  1441.   gotoxy (1, SC_HEADER + 12);
  1442.   textcolor (MESSAGE_HIGHLIGHT);
  1443.   cprintf ("Q");
  1444.   textcolor (MESSAGE_FCOLOR);
  1445.   cprintf ("uantization: ");
  1446.   if (twopassF)
  1447.     cprintf ("Two pass.");
  1448.   else
  1449.     cprintf ("One Pass.");
  1450.   while (!quitF)
  1451.     {
  1452.       gotoxy (1, SC_HEIGHT - SC_FOOTER - 1);
  1453.       clreol ();
  1454.       cprintf ("Please enter your choice: ");
  1455.       c = getxkey ();
  1456.       switch (c)
  1457.     {
  1458.     case 'i':
  1459.     case 'I':
  1460.       GinterpF = !GinterpF;
  1461.       gotoxy (1, SC_HEADER + 8);
  1462.       clreol ();
  1463.       textcolor (MESSAGE_HIGHLIGHT);
  1464.       cprintf ("I");
  1465.       textcolor (MESSAGE_FCOLOR);
  1466.       cprintf ("nterpolation: ");
  1467.       if (GinterpF)
  1468.         cprintf ("Linear Averaging.\n");
  1469.       else
  1470.         cprintf ("None.\n");
  1471.       clreol ();
  1472.       break;
  1473.     case 'd':
  1474.     case 'D':
  1475.       ditherF = !ditherF;
  1476.       gotoxy (1, SC_HEADER + 9);
  1477.       clreol ();
  1478.       textcolor (MESSAGE_HIGHLIGHT);
  1479.       cprintf ("D");
  1480.       textcolor (MESSAGE_FCOLOR);
  1481.       cprintf ("ithering: ");
  1482.       if (ditherF)
  1483.         cprintf ("Floyd-Steinberg.\n");
  1484.       else
  1485.         cprintf ("None.\n");
  1486.       clreol ();
  1487.       break;
  1488.     case 'g':
  1489.     case 'G':
  1490.       gotoxy (1, SC_HEIGHT - SC_FOOTER - 1);
  1491.       clreol ();
  1492.       cprintf ("Please enter gamma: ");
  1493.       Gamma = getdouble ();
  1494.       MakeColorLUT (ColorLUT, 0, 255, 0, 31, Gamma);
  1495.       ColorLUT[256] = ColorLUT[255];/* to take care of rounding errors */
  1496.       MakeColorLUT (ColorLUT256, 0, 255, 0, 255, Gamma);
  1497.       ColorLUT256[256] = ColorLUT256[255];
  1498.       
  1499.       gotoxy (1, SC_HEADER + 5);
  1500.       clreol ();
  1501.       textcolor (MESSAGE_HIGHLIGHT);
  1502.       cprintf ("G");
  1503.       textcolor (MESSAGE_FCOLOR);
  1504.       cprintf ("amma: %0.2lf\n", Gamma);
  1505.       break;
  1506.     case 'b':
  1507.     case 'B':
  1508.       blocksmoothF = !blocksmoothF;
  1509.       gotoxy (1, SC_HEADER + 3);
  1510.       clreol ();
  1511.       textcolor (MESSAGE_HIGHLIGHT);
  1512.       cprintf ("B");
  1513.       textcolor (MESSAGE_FCOLOR);
  1514.       cprintf ("lock smoothing: ");
  1515.       if (blocksmoothF)
  1516.         cprintf ("Yes.");
  1517.       else
  1518.         cprintf ("No.");
  1519.       break;
  1520.     case 'p':
  1521.     case 'P':
  1522.       pixelsmoothF = !pixelsmoothF;
  1523.       gotoxy (1, SC_HEADER + 4);
  1524.       clreol ();
  1525.       textcolor (MESSAGE_HIGHLIGHT);
  1526.       cprintf ("P");
  1527.       textcolor (MESSAGE_FCOLOR);
  1528.       cprintf ("ixel smoothing: ");
  1529.       if (pixelsmoothF)
  1530.         cprintf ("Yes.");
  1531.       else
  1532.         cprintf ("No");
  1533.       break;
  1534.     case 'q':
  1535.     case 'Q':
  1536.       twopassF = !twopassF;
  1537.       gotoxy (1, SC_HEADER + 12);
  1538.       clreol ();
  1539.       textcolor (MESSAGE_HIGHLIGHT);
  1540.       cprintf ("Q");
  1541.       textcolor (MESSAGE_FCOLOR);
  1542.       cprintf ("uantization: ");
  1543.       if (twopassF)
  1544.         cprintf ("Two pass.");
  1545.       else
  1546.         cprintf ("One Pass.");
  1547.       break;
  1548.     case 'h':
  1549.     case 'H':
  1550.       if (!nohicolor)
  1551.         {
  1552.           hicolorF = !hicolorF;
  1553.           gotoxy (1, SC_HEADER + 2);
  1554.           clreol ();
  1555.           textcolor (MESSAGE_HIGHLIGHT);
  1556.           cprintf ("H");
  1557.           textcolor (MESSAGE_FCOLOR);
  1558.           cprintf ("icolor: ");
  1559.           if (hicolorF)
  1560.         cprintf ("Used.");
  1561.           else
  1562.         cprintf ("Not used.");
  1563.         }
  1564.       break;
  1565.     case ESC:
  1566.       quitF = 1;
  1567.       break;
  1568.     }
  1569.     }                /* while */
  1570.  
  1571.  
  1572. }
  1573.  
  1574. void
  1575. userint ()
  1576. {
  1577.   int quitF = 0;
  1578.   int fileoffset = 0;
  1579.   int currentpos = 0;
  1580.   int onscreen;
  1581.   int specialF;
  1582.   int c;
  1583.   int colheight;
  1584.  
  1585.  
  1586.   colheight = SC_HEIGHT - SC_HEADER - SC_FOOTER;
  1587.   onscreen = colheight * SC_COLS;
  1588.  
  1589.   clrscr ();
  1590.   draw_border ();
  1591.   print_files (fileoffset, currentpos);
  1592.   while (!quitF)
  1593.     {
  1594.       c = getxkey ();
  1595.       switch (c)
  1596.     {
  1597.     case UP:
  1598.       currentpos--;
  1599.       if (currentpos < 0)
  1600.         currentpos = 0;
  1601.       else if (currentpos < fileoffset)
  1602.         {
  1603.           fileoffset--;
  1604.           print_files (fileoffset, currentpos);
  1605.         }
  1606.       else
  1607.         {
  1608.           highlight (fileoffset, currentpos + 1, 0);
  1609.           highlight (fileoffset, currentpos, 1);
  1610.         }
  1611.       break;
  1612.     case DOWN:
  1613.       currentpos++;
  1614.       if (currentpos >= totalfiles)
  1615.         currentpos = totalfiles - 1;
  1616.       else if (currentpos > fileoffset + onscreen - 1)
  1617.         {
  1618.           fileoffset++;
  1619.           print_files (fileoffset, currentpos);
  1620.         }
  1621.       else
  1622.         {
  1623.           highlight (fileoffset, currentpos - 1, 0);
  1624.           highlight (fileoffset, currentpos, 1);
  1625.         }
  1626.       break;
  1627.     case RIGHT:
  1628.       highlight (fileoffset, currentpos, 0);
  1629.       currentpos += colheight;
  1630.       if (currentpos >= totalfiles)
  1631.         currentpos = totalfiles - 1;
  1632.  
  1633.       if (currentpos > fileoffset + onscreen - 1)
  1634.         {
  1635.           fileoffset += colheight;
  1636.           print_files (fileoffset, currentpos);
  1637.         }
  1638.       else
  1639.         {
  1640.           highlight (fileoffset, currentpos, 1);
  1641.         }
  1642.       break;
  1643.     case LEFT:
  1644.       highlight (fileoffset, currentpos, 0);
  1645.       currentpos -= colheight;
  1646.       if (currentpos < 0)
  1647.         currentpos = 0;
  1648.       if (currentpos < fileoffset)
  1649.         {
  1650.           fileoffset -= colheight;
  1651.           if (fileoffset < 0)
  1652.         fileoffset = 0;
  1653.           print_files (fileoffset, currentpos);
  1654.         }
  1655.       else
  1656.         {
  1657.           highlight (fileoffset, currentpos, 1);
  1658.         }
  1659.       break;
  1660.     case 'o':
  1661.     case 'O':
  1662.       optionsmenu ();
  1663.       clrscr ();
  1664.       draw_border ();
  1665.       print_files (fileoffset, currentpos);
  1666.       break;
  1667.     case ESC:
  1668.       return;
  1669.       break;
  1670.     case RETURN:
  1671.       switch (moh_files[currentpos].type)
  1672.         {
  1673.         case FMT_JFIF:
  1674.           read_JPEG_file (moh_files[currentpos].name);
  1675.           break;
  1676.         case FMT_TARGA:
  1677.           read_TARGA_file (moh_files[currentpos].name);
  1678.           break;
  1679.         case FMT_GIF:
  1680.           read_GIF_file (moh_files[currentpos].name);
  1681.           break;
  1682.         }
  1683.       getch ();
  1684.       GrSetMode (GR_80_25_text);
  1685.       draw_border ();
  1686.       print_files (fileoffset, currentpos);
  1687.  
  1688.       break;
  1689.     case 'q':
  1690.       quitF = 1;
  1691.       break;
  1692.     }
  1693.     }                /* while */
  1694. }
  1695.  
  1696.  
  1697. main (int argc, char **argv)
  1698. {
  1699.   char *fname;
  1700.   IMAGE_FORMATS filetype;
  1701.   int i, j, a;
  1702.  
  1703.  
  1704.   debugF = 0;
  1705.   scaleF = 1;
  1706.   sameaspectF = 1;
  1707.   GinterpF = 1;
  1708.   interpF = 1;
  1709.   Gamma = 1.0;
  1710.   blocksmoothF = 0;
  1711.   pixelsmoothF = 0;
  1712.   twopassF = 0;
  1713.   filetype = FMT_JFIF;
  1714.   ditherF = 0;
  1715.   if (debugF)
  1716.     for (i = 0; i < argc; i++)
  1717.       printf ("%s\n", argv[i]);
  1718.   nohicolor = 1;
  1719.  
  1720.   parse_command (argc, argv);
  1721.   if (debugF)
  1722.     {
  1723.       printf ("parsed %d files\n", totalfiles);
  1724.       for (i = 0; i < totalfiles; i++)
  1725.         printf ("%s\n", moh_files[i].name);
  1726.       getch ();
  1727.     }
  1728.   gppconio_init ();
  1729.   if (totalfiles)
  1730.     {
  1731.         MakeColorLUT (ColorLUT, 0, 255, 0, 31, Gamma);
  1732.         ColorLUT[256] = ColorLUT[255];/* to take care of rounding errors */
  1733.         MakeColorLUT (ColorLUT256, 0, 255, 0, 255, Gamma);
  1734.         ColorLUT256[256] = ColorLUT256[255];
  1735. #ifdef OLD_DRIVERS 
  1736.         F1024 = F800 = F640 =0;
  1737.         GrSetMode(GR_width_height_graphics,640,480);
  1738.         if (GrSizeX()==640 && GrSizeY()==480) F640=1;
  1739.         if (GrSizeX()==800 && GrSizeY()==600) F800=1;
  1740.         if (GrSizeX()==1024 && GrSizeY()==768) F1024=1;
  1741.         GrSetMode (GR_80_25_text);
  1742.         if (F640==F1024==F800==0)
  1743.         {
  1744.             printf("Sorry, Video card not supported.\n");
  1745.             exit(1);
  1746.         }
  1747. #else
  1748.         GrGetDriverModes (&ttab, >ab);
  1749.         F1024 = F800 = F640 = hi800F = hi640F = 0;
  1750.         for (i = 0; gtab[i].width != 0; i++)
  1751.         {
  1752.             if (gtab[i].number_of_colors == 32768)
  1753.             nohicolor = 0;
  1754.             if (gtab[i].width == 1024 && gtab[i].height == 768 &&
  1755.             gtab[i].number_of_colors == 256)
  1756.             F1024 = 1;
  1757.             if (gtab[i].width == 800 && gtab[i].height == 600 &&
  1758.             gtab[i].number_of_colors == 256)
  1759.             F800 = 1;
  1760.             if (gtab[i].width == 640 && gtab[i].height == 480 &&
  1761.             gtab[i].number_of_colors == 256)
  1762.             F640 = 1;
  1763.             if (gtab[i].width == 800 && gtab[i].height == 600 &&
  1764.             gtab[i].number_of_colors == 32768)
  1765.             hi800F = 1;
  1766.             if (gtab[i].width == 640 && gtab[i].height == 480 &&
  1767.             gtab[i].number_of_colors == 32768)
  1768.             hi640F = 1;
  1769.         }
  1770.         if (F640==F1024==F800==hi800F==hi640F==0)
  1771.         {
  1772.             printf("Sorry, Video card not supported.\n");
  1773.             exit(1);
  1774.         }
  1775. #endif
  1776.       if (nohicolor)
  1777.           hicolorF = 0;
  1778.       else
  1779.           hicolorF = 1;
  1780.       userint ();
  1781.       GrSetMode (GR_80_25_text);
  1782.     }
  1783.   else printf("No files found");
  1784.   return 0;
  1785. }
  1786.  
  1787. void
  1788. mr_prints (int x, int y, int attr, char *str)
  1789. {
  1790.   while (*str)
  1791.     {
  1792.       if (*str == '\t')
  1793.     x = (x / 8) * 8 + 8;
  1794.       else if (*str == '\n')
  1795.     y++;
  1796.       else
  1797.     ScreenPutChar (*(str++), attr, x++, y);
  1798.       if (x >= 80)
  1799.     {
  1800.       y++;
  1801.       x = 0;
  1802.     }
  1803.     }
  1804. }
  1805.